import { reaction } from 'mobx';
import { DeviceEventEmitter } from 'react-native'
import { userStore, webSocketStore, deviceStore } from '~/store';
import { getUserCourse, startCourse, switchCourse } from '~/utils/course';
import { setLaserTreatmentParameters, setLaserTimeOut, LaserTreatmentInterval } from '~/utils/ble/application';
import { linkSubDevice } from '~/utils/socketMessenger';
import { updateBindCourseIdApi, checkStartCourseStateApi } from '~/api/acupoints';

// ========== 常量定义 ==========
const DEFAULT_CONNECTION_TIMEOUT = 8000; // 默认连接超时时间(毫秒)
const MAX_CONNECTION_RETRIES = 3;       // 最大连接重试次数
const RETRY_INTERVAL = 5000;            // 重试间隔3秒(毫秒)
const WRITE_COURSE_TIMEOUT = 15000;     // 写入疗程超时时间(毫秒)
const TREATMENT_DURATION = 6000;        // 单设备治疗持续时间(毫秒)

// ========== 类型定义 ==========
interface LaserParams {
    [key: string]: any;
}

interface DeviceInfo {
    armarium_device_chang: string;
    user_course_id: string;
    device_id: string
    course_id: string
}

interface ConnectionParams {
    sn_id: string;
    set_state: number;
    timestamp?: number;
}

// ========== 共享状态变量 ==========
let laserParams: LaserParams = {};
let currentCourseParams = {
    type: "ble",
    subDevice_sn: "",
    device_sn: "",
    pupillus_mobile: userStore.me.mobile
};
let currentCourseId = '';
let action_type = 'start'
let writeCourseResolver: { resolve: (value?: unknown) => void; reject: (reason?: any) => void } | null = null; let writeCourseTimeout: NodeJS.Timeout | null = null;
let isProcessing = false;
let currentProcessingDevice: string | null = null;

// 替换更新使用
let device_id = ''
let course_id = ''



/**
 * 带超时和3秒重试间隔的设备连接
 */
export const linkSubDeviceWithTimeout = async (
    device_sn: string,
    { sn_id, set_state }: { sn_id: string; set_state: number },
    timeout: number = DEFAULT_CONNECTION_TIMEOUT,
    maxRetries: number = MAX_CONNECTION_RETRIES
): Promise<{ status: number }> => {
    let retryCount = 0;
    let disposer: (() => void) | null = null;
    let currentTimer: NodeJS.Timeout | null = null;

    const cleanup = () => {
        if (disposer) {
            disposer();
            disposer = null;
        }
        if (currentTimer) {
            clearTimeout(currentTimer);
            currentTimer = null;
        }
    };

    while (retryCount < maxRetries) {
        try {
            console.log(`[设备连接] 尝试第 ${retryCount + 1} 次连接设备 ${sn_id}`);

            // 重置状态确保新的 reaction 能正确捕获变化
            webSocketStore.linkSubDeviceStatus = null;

            const result = await new Promise<{ status: number }>((resolve, reject) => {
                // 设置超时
                currentTimer = setTimeout(() => {
                    cleanup();
                    reject(new Error('连接超时'));
                    // linkSubDevice(device_sn, { sn_id, set_state: 0 });
                }, timeout);

                // 设置反应
                disposer = reaction(
                    () => webSocketStore.linkSubDeviceStatus,
                    (newStatus) => {
                        if (newStatus !== null) {
                            cleanup();
                            newStatus === 1 ? resolve({ status: 1 }) : reject(new Error('无法连接'));
                        }
                    },
                    { fireImmediately: false } // 改为 false 避免立即触发
                );

                // 发起连接
                linkSubDevice(device_sn, { sn_id, set_state });
            });

            return result;
        } catch (error: any) {
            retryCount++;
            console.error(`[设备连接] 第 ${retryCount} 次失败: ${error.message}`);
            cleanup(); // 确保清理

            if (retryCount >= maxRetries) {
                throw new Error(`设备 ${sn_id} 已经尝试了 ${maxRetries} 次连接失败`);
            }

            // 等待重试间隔
            console.log(`[设备连接] 等待 ${RETRY_INTERVAL / 1000}秒后重试...`);
            await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
        }
    }

    throw new Error('连接流程异常');
};

/**
 * 安全断开设备连接
 */
const safelyDisconnectDevice = async (device_sn: string, subDevice_sn: string, status: number) => {
    try {
        console.log(`[断开连接] 开始断开设备 ${subDevice_sn}`);

        linkSubDevice(device_sn, {
            sn_id: subDevice_sn,
            set_state: 0,
        });

        await new Promise<void>((resolve) => {
            let disposer: (() => void) | null = null;
            const timeoutId = setTimeout(() => {
                disposer?.();
                resolve();
            }, 3000);

            disposer = reaction(
                () => webSocketStore.linkSubDeviceStatus,
                (status) => {
                    if (status === 0) {
                        disposer?.();
                        clearTimeout(timeoutId);
                        resolve();
                    }
                }
            );
        });

        webSocketStore.updateDeviceStatus(subDevice_sn, status !== 1 ? 2 : 1);
    } catch (error) {
        console.error(`[断开连接] 设备 ${subDevice_sn} 断开异常:`, error);
    }
};

/**
 * 写入疗程参数到设备
 */
let writeCourseTimeoutId: NodeJS.Timeout | null = null;
let retryTimer: NodeJS.Timeout | null = null;
let isWaitingForLaserParams = false;


const writeCourseToDevice = async (
    user_course_id: string,
    subDevice_sn: string,
    device_sn: string,
    actionType: string
): Promise<void> => {
    currentCourseParams = { ...currentCourseParams, subDevice_sn, device_sn };
    currentCourseId = user_course_id;
    action_type = actionType

    console.log("user_course_id, subDevice_sn", user_course_id, subDevice_sn)
    const { status, laserParams: params } = await getUserCourse(user_course_id, subDevice_sn, '');
    if (status !== 1) {
        linkSubDevice(device_sn, { sn_id: subDevice_sn, set_state: 0 });
        throw new Error('获取疗程参数失败');
    }

    laserParams = params;

    await new Promise<void>(async (resolve, reject) => {
        writeCourseResolver = { resolve, reject };
        writeCourseTimeoutId = setTimeout(() => {
            // linkSubDevice(device_sn, { sn_id: subDevice_sn, set_state: 0 });
            reject(new Error('写入疗程超时'));
        }, 5000); // 5秒超时

        try {
            await setLaserTreatmentParameters(laserParams, currentCourseParams);
        } catch (err) {
            reject(err);
        }
    });
};

// 新增工具函数清理计时器
function clearWriteCourseTimeout() {
    if (writeCourseTimeoutId) {
        clearTimeout(writeCourseTimeoutId);
        writeCourseTimeoutId = null;
    }
}

// ========== BLE回调处理 ==========

// 开始写入、切换相关逻辑判断
async function handleCourseAction() {
    const { subDevice_sn, device_sn } = currentCourseParams;
    const commonParams = { user_course_id: currentCourseId, device_sn: subDevice_sn, mobile: '', type: 1 };
    console.log("action_typeaction_typeaction_type", action_type)
    if (action_type == 'start') {
        const checkStatus = await checkStartCourseStateApi({ device_sn: subDevice_sn });
        console.log("checkStatuscheckStatus", checkStatus)
        const isStart = checkStatus.msg == 1;
        const result = isStart ? await startCourse(commonParams) : await switchCourse(commonParams);
        // const result = await startCourse(commonParams)
        console.log('写入疗程>>>>>', result);
        await processCourseResult(result, device_sn, subDevice_sn);
    } else {
        const result = await switchCourse(commonParams);
        console.log("切换疗程1111", result);
        await processCourseResult(result, device_sn, subDevice_sn);
    }
}
async function processCourseResult(result, deviceId, subDevice_sn) {
    if (result.status === 1) {
        console.log("开始告诉后台更新参数>>>>>>", device_id, course_id);
        const res1 = await updateBindCourseIdApi({ device_id, course_id });
        console.log("updateBindCourseIdApi response", res1);
        deviceStore.disConnectble()
        Toast.show({ content: "激活疗程成功" })
        DeviceEventEmitter.emit("writeSuccess", 1)
        // await safelyDisconnectDevice(deviceId, subDevice_sn, res1.returnData);
    } else {
        DeviceEventEmitter.emit("writeSuccess", 0)
        deviceStore.disConnectble()
        Toast.show({ content: result.msg })
        // await safelyDisconnectDevice(deviceId, subDevice_sn, 0);
    }
}

deviceStore.bleCallback(async (res: { type: string; status: number }) => {
    // if (!res?.type || res.status !== 0 || !currentProcessingDevice) return;
    if (userStore.isRole !== 'Acupoints') return
    try {
        switch (res.type) {
            case "setLaserParams":
                console.log("[BLE回调] 激光参数设置完成", res);

                // 清除可能存在的重试计时器
                if (retryTimer) {
                    clearTimeout(retryTimer);
                    retryTimer = null;
                }

                // 标记不再等待
                isWaitingForLaserParams = false;
                await LaserTreatmentInterval(laserParams, currentCourseParams);
                writeCourseResolver?.resolve();
                clearWriteCourseTimeout();
                break;

            case "setLaserInterval":
                console.log("[BLE回调] 激光间隔设置完成", res);
                if (deviceStore.course.courseIntervalStatus) {
                    await setLaserTimeOut(1, currentCourseParams);
                }
                writeCourseResolver?.resolve();
                clearWriteCourseTimeout();
                break;

            case "setLaserRegimen":
                console.log("[BLE回调] 激光疗程设置完成", res);
                writeCourseResolver?.resolve();
                clearWriteCourseTimeout();
                handleCourseAction()
                break;
        }
    } catch (error) {
        console.error("[BLE回调] 处理错误:", error);
    }
});

// ========== 设备流程控制 ==========


/**
 * 处理单个设备完整流程
 */
const processSingleDevice = async (
    device: DeviceInfo,
    device_sn: string,
    actionType: string
): Promise<void> => {
    const deviceId = device.armarium_device_chang;
    currentProcessingDevice = deviceId;
    device_id = device.device_id
    course_id = device.course_id

    try {
        console.log(`[设备流程] 开始处理设备 ${deviceId}`);
        webSocketStore.updateDeviceStatus(deviceId, 3);
        // 1. 连接设备（带重试）
        const res = await linkSubDeviceWithTimeout(device_sn, {
            sn_id: deviceId,
            set_state: 1
        });

        // 2. 写入疗程参数（带自动重试）
        await writeCourseToDeviceWithRetry(
            device.user_course_id,
            deviceId,
            device_sn,
            1,
            actionType
        );

        // 3. 等待治疗完成
        await new Promise(resolve => setTimeout(resolve, TREATMENT_DURATION));

        console.log(`[设备流程] 设备 ${deviceId} 处理完成`);
        // webSocketStore.updateDeviceStatus(deviceId, 1); // 标记成功
    } catch (error: any) {
        console.error(`[设备流程] 设备 ${deviceId} 处理失败:`, error);
        webSocketStore.updateDeviceStatus(
            deviceId,
            error.message.includes('超时') ? 4 : 5
        );
        throw error; // 仍然抛出错误，由外层处理
    } finally {
        if (currentProcessingDevice === deviceId) {
            currentProcessingDevice = null;
        }
    }
};

const writeCourseToDeviceWithRetry = async (
    user_course_id: string,
    subDevice_sn: string,
    device_sn: string,
    maxRetries = 1, // 默认重试1次
    actionType: string
): Promise<void> => {
    let lastError;

    for (let attempt = 0; attempt <= maxRetries; attempt++) {
        try {
            return await writeCourseToDevice(user_course_id, subDevice_sn, device_sn, actionType);
        } catch (error: any) {
            lastError = error;
            if (error.message === '获取疗程参数失败') {
                webSocketStore.updateDeviceStatus(subDevice_sn, 6);
                console.warn(`[参数写入] 获取疗程参数失败，跳过重试`);
                throw error;
            }
            console.log(`[参数写入] 第 ${attempt + 1} 次尝试失败，等待重试...`, error);
            if (attempt < maxRetries) {
                await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒再重试
            }
        }
    }

    throw lastError || new Error('参数写入失败');
};
/**
 * 主流程：按顺序处理所有设备
 */
export const processDevices = async (
    deviceList: DeviceInfo[],
    device_sn: string,
    actionType: string
): Promise<{ success: boolean; processedCount: number }> => {
    if (isProcessing) {
        console.warn('[流程控制] 已有设备处理流程在进行中');
        return { success: false, processedCount: 0 };
    }
    isProcessing = true;
    let processedCount = 0;
    try {
        for (const device of deviceList) {
            if (!isProcessing) break;
            try {
                await processSingleDevice(device, device_sn, actionType);
                processedCount++;
            } catch (error) {
                webSocketStore.linkSubDeviceStatus = 0
                console.error(`[流程控制] 设备 ${device.armarium_device_chang} 处理失败，继续下一个`, error);
            }
        }
        const success = processedCount === deviceList.length;
        console.log(`[流程控制] 处理完成，成功 ${processedCount}/${deviceList.length}`);
        return { success, processedCount };

    } catch (error) {
        console.error('[流程控制] 设备处理流程出错:', error);
        return { success: false, processedCount };
    } finally {
        isProcessing = false;
        currentProcessingDevice = null;
    }
};
/**
 * 停止当前处理流程
 */
export const stopProcessing = () => {
    if (isProcessing) {
        console.log('[流程控制] 手动停止设备处理流程');
        isProcessing = false;
    }
};




export const byBlewriteDevice = async (info, actionType): Promise<void> => {
    // const { course_id, user_course_id, armarium_device_chang, device_id } = info
    // writeCourseToDevice( actionType);
    currentCourseParams = { ...currentCourseParams, subDevice_sn: info.armarium_device_chang, };
    currentCourseId = info.user_course_id;
    action_type = actionType
    device_id = info.device_id
    course_id = info.course_id
    const { status, laserParams: params, msg } = await getUserCourse(info.user_course_id, info.armarium_device_chang, '');
    console.log("获取的疗程详情", status, params)
    if (status !== 1) {

        deviceStore.disConnectble()
        Toast.show({ content: msg })
        return
    }
    laserParams = params;
    await new Promise<void>(async (resolve, reject) => {
        writeCourseResolver = { resolve, reject };
        writeCourseTimeoutId = setTimeout(() => {
            Toast.show({ content: "写入疗程超时" })
            // linkSubDevice(device_sn, { sn_id: subDevice_sn, set_state: 0 });
            reject(new Error('写入疗程超时'));
        }, 5000); // 5秒超时

        try {
            await setLaserTreatmentParameters(laserParams, currentCourseParams);
        } catch (err) {
            console.log("设置激光疗程errerrerrerrerrerr", err)
            reject(err);
        }
    });
}